﻿//HAAR Wavelet
namespace Diplom.Wavelets
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Diplom.NumericArrays;

    public static class HAAR
    {
        private static Double EPS = 1e-9;
        private static Double Base = 2.0;
        private static Double Move = 1;

        /// <summary>
        /// Wavelet function
        /// </summary>
        public static double HaarWavelet(double x)
        {
            if (x >= -EPS && x * 2< 1) return 1;
            else
            {
                if (2 * x >= 1 - EPS && x < 1) return -1;
                else
                    return 0;
            }            
                    
        }

        /// <summary>
        /// Wavelet transform
        /// </summary>
        public static Numeric2DArray Transform(ref Numeric1DArray source)
        {
            int m = 0;
            double cur = 1;
            while (cur <= source.Length)
            {
                m++;
                cur *= Base;
            }
            Numeric2DArray waveCoeff = new Numeric2DArray(m + 1, (int)cur + 1);
            for (int i = 0; i <= m; i++)
            {
                double a = 1 / Math.Pow(Base, i + 0.0);
                double sqrt_a = Math.Sqrt(a);
                for (int j = 0; j <= (int)cur; j++)
                {
                    double res = 0;
                    for (int k = 0; k < source.Length; k++)
                    {
                        double phi = HaarWavelet(k * a - j * Move);
                        res += (source.Items[k] * phi);
                    }
                    res *= sqrt_a;
                    waveCoeff.Insert(i, j, res);
                }
            }
            waveCoeff.InitCharacters();
            return waveCoeff;
        }

        /// <summary>
        /// Wavelet syntes
        /// </summary>        
        public static Numeric1DArray Syntes(ref Numeric2DArray source,int size)
        {
            Numeric1DArray signal = new Numeric1DArray(size);
            for (int k = 0; k < size; k++)
            {
                double res = 0;
                for (int i = 0; i < source.NSize; i++)
                {
                    double a = 1.0 / Math.Pow(Base, i + 0.0);
                    double sqrt_a = Math.Sqrt(a);
                    for (int j = 0; j < source.MSize; j++)
                    {
                        double phi = HaarWavelet(k * a - j * Move);
                        res+=(source.Items[i][j]*phi)*sqrt_a;
                    }
                }                
                res /= 2.0;
                signal.Insert(k, res);
            }
            signal.InitCharacters();
            return signal;
        }

    }
}
